using System;
using System.Data;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using System.Web.UI.WebControls;

using SBPweb.Data;

namespace SBPweb.Controls.Web
{


	public class EntityDataTableSource<T> : DataTable, IEntityListSource where T : Entity
	{

		#region Private fields

		private List<T> mList;
		private Dictionary<string, byte> mPICounts = new Dictionary<string,byte>();

		#endregion

		#region Constructor logic

		public EntityDataTableSource(List<T> list)
		{
			mList = list;

			base.BeginInit();

			foreach(string str in Entity.Columns[ItemType])
			{
				DataColumn column = new DataColumn(str);
				 
				PropertyInfo pI = null;
				PropertyInfo[] pIs = ItemType.GetProperties(BindingFlags.Default | BindingFlags.Instance | BindingFlags.Public);

				mPICounts[str] = 0;

				foreach(PropertyInfo cpi in pIs)
				{
					if (cpi.Name == str)
					{
						pI = cpi;
						mPICounts[str]++;
					}
				}

				if (pI != null)
				{
					column.DataType = pI.PropertyType;
				}

				if (Columns.Contains(str))
				{
					Columns.Remove(str);
				}
				
				Columns.Add(column);
			}

			foreach (T item in list)
			{
				Rows.Add(CreateNewEntityRowInstance(item));
			}

			base.AcceptChanges();
			base.EndInit();
		}

		private DataRow CreateNewEntityRowInstance(T entity)
		{
			DataRow row = base.NewRow();

			row.BeginEdit();
			foreach (DataColumn dc in Columns)
			{
				if (mPICounts[dc.ColumnName] > 1)
				{
					row[dc] = entity.GetValue<object>(dc.ColumnName + "New");
				}
				else
				{
					row[dc] = entity.GetValue<object>(dc.ColumnName);
				}
			}
			row.EndEdit();

			return row;
		}

		#endregion

		#region Public methods

		public T GetItemByDataRow(DataRow dr)
		{
			int i = Rows.IndexOf(dr);

			if (i == -1)
			{
				return default(T);
			}

			return mList[i];
		}

		#endregion

		#region IEntityListSource Members

		public Type ItemType
		{
			get
			{
				return typeof(T);
			}
		}

		public Array AsArray
		{
			get
			{
				return base.Select();
			}
		}

		public IList AsList
		{
			get
			{
				return mList;
			}
		}

		public void Sort(string expression, SortDirection direction)
		{
			throw new Exception("The method or operation is not implemented.");
		}

		#endregion

	}
}